<script setup lang="ts">
  import type { DishFlavorEntity } from '@/shared/entity/dish'
  import { isEmpty, pick } from 'lodash-es'
  import { computed, reactive, ref, toRef, useTemplateRef, watch, watchEffect } from 'vue'
  import { useDishCategory } from '@/datas/use-dish-category'
  import {
    CategoryTypeEnum,
    INIT_AUTH_HEADER,
    DishFlavorNameOptions,
    DishStatusEnum
  } from '@/shared'
  import { getAuthHeader } from '@/utils/auth'
  import { Message } from '@arco-design/web-vue'
  import { DoPost, DoPut } from '@/utils/http'
  import { useDishRecord } from '@/datas/use-dish-record'

  interface IProps {
    id?: number
  }

  const props = defineProps<IProps>()

  const emits = defineEmits<{
    (e: 'refresh'): void
    (e: 'clear'): void
  }>()

  const { data } = useDishCategory(CategoryTypeEnum.Dish)

  const categoryTypeList = computed(() => {
    return data?.value?.data?.map(item => ({
      label: item.name,
      value: item.id
    }))
  })

  const visible = defineModel({
    type: Boolean || undefined
  })

  const formRef = useTemplateRef('formRef')

  const defaultFormData = {
    name: '',
    categoryId: undefined,
    price: undefined,
    flavors: [{}],
    image: '',
    description: '',
    status: DishStatusEnum.Enable
  }

  const formData = reactive<Record<string, any>>(structuredClone(defaultFormData))

  const file = ref()

  const isEdit = computed(() => props.id)

  const refId = toRef(props, 'id')

  const record = useDishRecord(refId)

  watch(record, val => {
    Object.assign(
      formData,
      pick(val, ['name', 'categoryId', 'price', 'image', 'description', 'status'])
    )
    if (val?.flavors.length) {
      formData.flavors = val.flavors.map(item => ({
        ...item,
        value: JSON.parse(item.value || '[]')
      }))
    }
    if (val?.image) {
      file.value = {
        uid: `${Date.now()}-0`,
        file: {},
        url: val.image,
        name: `${Date.now}`,
        status: 'done',
        percent: 1,
        response: '{}'
      }
    }
  })

  watch(visible, val => {
    if (!val) {
      Object.assign(formData, defaultFormData)
      emits('clear')
    }
  })

  const customRequest = (option: any) => {
    const { onProgress, onError, onSuccess, fileItem, name } = option
    const xhr = new XMLHttpRequest()
    if (xhr.upload) {
      xhr.upload.onprogress = function (event) {
        let percent
        if (event.total > 0) {
          // 0 ~ 1
          percent = event.loaded / event.total
        }
        onProgress(percent, event)
      }
    }
    xhr.onerror = function error(e) {
      onError(e)
    }
    xhr.onload = function onload() {
      if (xhr.status < 200 || xhr.status >= 300) {
        return onError(xhr.responseText)
      }
      onSuccess(xhr.response)
    }

    const formData = new FormData()
    formData.append(name || 'file', fileItem.file)
    xhr.open('post', '/api/admin/common/upload', true)
    xhr.setRequestHeader(INIT_AUTH_HEADER, getAuthHeader() || '')
    xhr.send(formData)

    return {
      abort() {
        xhr.abort()
      }
    }
  }

  const beforeUpload = async (file: File) => {
    const size = file.size / 1024 / 1024
    if (size > 2) {
      Message.error('图片大小不能超过2M')
      return false
    }
    return true
  }

  const handlerSubmit = async () => {
    const data = await formRef.value?.validate()
    if (!isEmpty(data)) return false
    const params = {
      ...formData,
      flavors: formData.flavors.map((item: DishFlavorEntity) => ({
        ...item,
        value: JSON.stringify(item.value)
      }))
    }
    if (isEdit.value) {
      await DoPut('/dish', {
        ...params,
        id: props.id
      })
      Message.success('编辑成功')
    } else {
      await DoPost('/dish', params)
      Message.success('添加成功')
    }
    emits('refresh')
  }
</script>

<template>
  <a-modal
    :title="isEdit ? '编辑菜品' : '添加菜品'"
    title-align="start"
    v-model:visible="visible"
    :mask="false"
    modal-class="create-dish"
    body-class="create-dish-body"
    class="create-wrapper"
    @before-ok="handlerSubmit"
  >
    <a-form :model="formData" layout="vertical" ref="formRef">
      <a-form-item field="name" label="菜品名称" :rules="[{ required: true }]">
        <a-input placeholder="请输入菜品名称" v-model="formData.name" />
      </a-form-item>
      <a-form-item field="categoryId" label="菜品分类" :rules="[{ required: true }]">
        <a-select
          placeholder="请选择菜品分类"
          :options="categoryTypeList"
          v-model="formData.categoryId"
          allow-clear
        />
      </a-form-item>
      <a-form-item field="price" label="菜品价格" :rules="[{ required: true }]">
        <a-input-number placeholder="请输入菜品价格" v-model="formData.price">
          <template #suffix>元</template>
        </a-input-number>
      </a-form-item>
      <a-form-item label="口味做法配置">
        <div class="fla-content">
          <div class="fla-content-body">
            <div>
              <p>口味名（3个字内）</p>
              <a-form-item
                v-for="(item, key) in formData.flavors"
                :key="key"
                :field="`formData[${key}].name`"
              >
                <a-select
                  :options="DishFlavorNameOptions"
                  v-model="item.name"
                  placeholder="请选择口味名称"
                  style="width: 204px"
                />
              </a-form-item>
            </div>
            <div>
              <p>口味标签（输入后，回车添加）</p>
              <a-form-item
                v-for="(item, key) in formData.flavors"
                :key="key"
                :field="`formData[${key}].value`"
              >
                <a-input-tag
                  v-model="item.value"
                  placeholder="输入后，回车添加"
                  style="width: 204px"
                />
              </a-form-item>
            </div>
          </div>
          <div class="fla-content-footer">
            <a-button
              type="primary"
              @click="
                () => {
                  formData.flavors.push({
                    name: '',
                    value: []
                  })
                }
              "
            >
              添加口味
            </a-button>
          </div>
        </div>
      </a-form-item>
      <a-form-item field="image" label="菜品图片" :rules="[{ required: true }]">
        <a-upload
          :show-file-list="false"
          :fileList="file ? [file] : []"
          :custom-request="customRequest"
          @before-upload="beforeUpload"
          accept="image/png, image/jpeg, image/jpg"
          @change="
            (_, currentFile) => {
              file = currentFile
              if (currentFile.status === 'done') {
                const resp = JSON.parse(currentFile.response)
                formData.image = resp.data
              }
            }
          "
          @progress="
            currentFile => {
              file = currentFile
            }
          "
        >
          <template #upload-button>
            <div
              :class="`arco-upload-list-item${
                file && file?.status === 'error' ? ' arco-upload-list-item-error' : ''
              }`"
            >
              <div
                class="arco-upload-list-picture custom-upload-avatar relative"
                v-if="file && file.url"
              >
                <img :src="file.url" />
                <div class="arco-upload-list-picture-mask">icon</div>

                <a-progress
                  v-if="file.status === 'uploading' && file?.percent < 100"
                  :percent="file?.percent"
                  type="circle"
                  size="mini"
                  :style="{
                    position: 'absolute',
                    left: '50%',
                    top: '50%',
                    transform: 'translateX(-50%) translateY(-50%)'
                  }"
                />
              </div>
              <div class="arco-upload-picture-card" v-else>
                <div class="arco-upload-picture-card-text">
                  icon
                  <div style="margin-top: 10px; font-weight: 600">Upload</div>
                </div>
              </div>
              <div class="ml-4">
                <p>图片大小不超过2M</p>
                <p>仅能上传PNG JPG JPEG类型图片</p>
                <p>建议上传200*200或300*300尺寸的图片</p>
              </div>
            </div>
          </template>
        </a-upload>
      </a-form-item>
      <a-form-item field="description" label="菜品描述" :rules="[{ required: true }]">
        <a-textarea
          placeholder="请输入菜品描述"
          v-model="formData.description"
          allow-clear
          :max-length="200"
        />
      </a-form-item>
    </a-form>
  </a-modal>
</template>

<style lang="less">
  .create-wrapper {
    .arco-modal-wrapper {
      overflow: hidden;
    }
  }
  .create-dish {
    border-color: #eaedf1 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    display: flex !important;
    flex-direction: column;
    height: calc(100% - 50px);
    margin: 60px 0 0 72px;
    width: calc(100% - 72px);
    &-body {
      flex: 1;
      overflow: auto;
    }
  }
</style>

<style lang="less" scoped>
  .fla-content {
    border: 1px solid var(--color-border);
    padding: 12px 10px;
    box-sizing: border-box;
    width: 100%;
    &-body {
      display: flex;
      gap: 16px;
    }
    &-footer {
      margin-top: 16px;
    }
  }
</style>
